/*
 * @lc app=leetcode.cn id=289 lang=cpp
 *
 * [289] 生命游戏
 */
#include "include.h"
// @lc code=start
class Solution {
public:
    void gameOfLife(vector<vector<int>>& board) {
        m = board.size();
        n = board.at(0).size();
// plotMatrix(board);
        for (int row=0;row<m;row++){
            for (int column=0;column<n;column++){
                convolutionKernel(row, column, board);
// plotMatrix(board);
            }
        }

        for (int row=0;row<m;row++){
            for (int column=0;column<n;column++){
                rebuild(row, column, board);
            }
        }
    }
private:
    int m = 0;
    int n = 0;
private:
    inline bool insideBoard(int row, int column){
        return row>=0 and row<m and column>=0 and column <n;
    }
    inline void convolutionKernel(int row, int column, vector<vector<int>>& board){
        int aliveCounter = 0;
        for (int i=0;i<8;i++){
            int currentRow = row + direction[i][0];
            int currentColumn = column + direction[i][1];
            if (insideBoard(currentRow, currentColumn)){
                if (board[currentRow][currentColumn] == origin_1 or
                    board[currentRow][currentColumn] == change_1_to_0 or
                    board[currentRow][currentColumn] == change_1_to_1){
                    aliveCounter += 1;
                }
            }
        }

        if (board[row][column] == 0){
            if (aliveCounter == 3){
                board[row][column] = change_0_to_1;
            } else{
                board[row][column] = change_0_to_0;
            }
        } else {
            if (aliveCounter<2){
                board[row][column] = change_1_to_0;
            } else if (aliveCounter>3){
                board[row][column] = change_1_to_0;
            } else {
                board[row][column] = change_1_to_1;
            }
        }
    }
    inline void rebuild(int row, int column, vector<vector<int>>& board){
        if (board[row][column] == change_0_to_0 or
            board[row][column] == change_1_to_0){
            board[row][column] = 0;
        } else{
            board[row][column] = 1;
        }
    }
    const int direction[8][2] = {
        {-1, -1},
        {-1, 0},
        {-1, 1},
        {0, -1},
        {0, 1},
        {1, -1},
        {1, 0},
        {1, 1}
    };
    enum status : unsigned int{
        origin_0 = 0,
        origin_1 = 1,

        change_0_to_0 = 2,
        change_0_to_1 = 3,
        change_1_to_0 = 4,
        change_1_to_1 = 5
    };
    void plotMatrix(const vector<vector<int>>& matrix){
        printf("-------------\n");
        for (int row=0;row<m;row++){
            for (int column=0;column<n;column++){
                printf("%d ", matrix[row][column]);
            }
            printf("\n");
        }
    }
};
// @lc code=end

int main(){
    vector<vector<int>> board {
        {0,1,0},
        {0,0,1},
        {1,1,1},
        {0,0,0}
    };
    Solution test;
    test.gameOfLife(board);
}